home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
seyon
/
SeTerm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
9KB
|
357 lines
/*
* This file is part of the Seyon, Copyright (c) 1992-1993 by Muhammad M.
* Saggaf. All rights reserved.
*
* See the file COPYING (1-COPYING) or the manual page seyon(1) for a full
* statement of rights and permissions for this program.
*/
/*
* This file contains routines for Seyon's terminal. The main routine is
* terminal(), which reads characters from the terminal and sends them to the
* port. That routine also forks a child process that reads characters from
* the port and writes them to the temrinal. Once the parent receives SIGTERM
* (which should be sent by the grand parent), it kills the child and exits.
*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <X11/Intrinsic.h>
#include "seyon.h"
#include "SeDecl.h"
extern char TtyReadChar();
extern int MdmReadStr();
extern FILE *tfp, /* terminal pointer */
*cfp; /* capture file pointer */
extern Boolean capture; /* are we capturing or not ? */
extern int tfd, /* terminal descriptor */
mainToTermPipe[];
extern pid_t mainPid;
void send_tbyte(),
toggle(),
cleanup();
pid_t readProcPid = 0; /* pid of child process */
/*---------------------------------------------------------------------------+
| DoNothingHandler - handler for doing nothing.
+---------------------------------------------------------------------------*/
void
DoNothingHandler(sigNum)
int sigNum;
{
#ifdef DEBUG
showf(">>> in DoNothingHandler, pid = %d, sig = %d", getpid(), sigNum);
#endif
/* Reinstall the signal handler */
signal(sigNum, DoNothingHandler);
}
/*---------------------------------------------------------------------------+
| TerminalKillHandler - handler for the terminal kill (SIGTERM).
+---------------------------------------------------------------------------*/
void
TerminalKillHandler(dummy)
int dummy;
{
signal(SIGTERM, SIG_IGN);
/* Kill the child process and wait for it to die, sounds vicious,
doesn't it? The child process is the read process from the port */
if (readProcPid && kill(readProcPid, SIGTERM) == 0)
while(wait((int*)0) < 0);
fflush(tfp);
exit(0);
}
/*---------------------------------------------------------------------------+
| TerminalSuspendHandler - handler for the terminal suspension (SIGUSR1).
+---------------------------------------------------------------------------*/
void
TerminalSuspendHandler(sigNum)
int sigNum;
{
/* Don't deliver or stack (as pending) any more instances of the signal
until we've woken up (below) */
signal(sigNum, SIG_IGN);
if (readProcPid) kill(readProcPid, sigNum);
pause();
#ifdef DEBUG
showf(">>> Terminal %d woke up - good", getpid());
#endif
/* After waking up */
if (readProcPid) kill(readProcPid, SIGCONT);
/* Reinstall the signal handler */
signal(sigNum, TerminalSuspendHandler);
}
/*---------------------------------------------------------------------------+
| TerminalRefreshParametersHandler - handler for the terminal to get the
| current session parameters (SIGUSR2).
+---------------------------------------------------------------------------*/
void
TerminalRefreshParametersHandler(sigNum)
int sigNum;
{
int PutParameters();
void GetParameters();
/* Don't deliver or stack (as pending) any more instances of the signal
until we're finished with the work at hand */
signal(sigNum, SIG_IGN);
GetParameters(NULL, mainToTermPipe);
if (readProcPid && (PutParameters(mainToTermPipe) < 0 ||
kill(readProcPid, sigNum) != 0))
SePError("Could not pipe parameters");
/* Reinstall the signal handler */
signal(sigNum, TerminalRefreshParametersHandler);
}
/*
* Terminal: main routine. Has two processes, one to read from terminal
* and send to the port and the other to do the oppsite.
*/
void
Terminal()
{
char c;
/* Tell the program where to go when signals are received */
signal(SIGTERM, TerminalKillHandler);
signal(SIGUSR1, TerminalSuspendHandler);
signal(SIGUSR2, TerminalRefreshParametersHandler);
signal(SIGCONT, DoNothingHandler);
signal(SIGCHLD, SIG_DFL);
/* Split into read and write processes */
/* Child, read proc: read from port and write to tty */
if ((readProcPid = SeFork()) == 0)
PortToTty();
/* Parent, write proc: read from tty and write to port */
while (1)
if (TtyReadChar(tfd, &c) >= 0) send_tbyte(c);
else {
SeError("TTY read error. Terminal process exiting");
if (readProcPid && kill(readProcPid, SIGTERM) == 0)
while(wait((int*)0) < 0);
ProcRequest(POPUP_ERROR, "TTY Read Error", "errReadError");
exit(1);
}
/*NOT REACHED*/
}
/*
* Read from the port and write to the tty
*/
void
PortToTty()
{
static char zmSig[] = "**\030B00";
static char *zmSigPtr = zmSig;
char buf[BUFSIZ], c;
int n, i;
signal(SIGTERM, TerminalKillHandler);
/* Let the main process know we're all set */
kill(mainPid, SIGCONT);
while (1) {
/* Read incoming charaters and exit the process if a read error
is encountered */
if ((n = MdmReadStr(buf)) < 0) {
SeError("Modem read error. Terminal process exiting");
ProcRequest(POPUP_ERROR, "Modem Read Error", "errReadError");
ProcRequest(KILL_TERM, "", "");
exit(1);
}
/* Write incoming characters to the tty */
fwrite(buf, sizeof(char), n, tfp);
fflush(tfp);
for(i = 0; i < n; i++) {
c = buf[i];
/* Write to capture file if capture is enabled */
if (capture) fputc(c, cfp);
/* Look for Zmodem signature */
if (c != *zmSigPtr)
zmSigPtr = zmSig;
else if (*++zmSigPtr == '\0' && qres.autoZmodem)
ProcRequest(DISPATCH_ACTION, "Zmodem Auto-Download",
qres.autoZmodemAction);
} /* for... */
} /* while(1)... */
/*NOT REACHED*/
}
/*
* send a translated character to the modem
*/
void
send_tbyte(c)
int c;
{
switch (c) {
/*Translate new line to carriage return if newline translation mode is
in effect*/
case '\n':
switch (newlineTrMode) {
case 2:
c = '\r';
break;
case 3:
sendbyte('\r');
default:
break;
}
break;
/*Translate backspace to delete if del translation mode is in effect*/
case 0x08:
if (qres.backspaceTranslation)
c = 0x7f;
break;
default:
break;
}
/*Send ESC before the character if meta key is pressed with the character
and the meta key translation mode is on*/
if (qres.metaKeyTranslation && (c & 0x80)) {
sendbyte('\033');
sendbyte(c);
}
/*Send the character to the port*/
else
sendbyte(c);
}
/*---------------------------------------------------------------------------+
| Routines to manipulate the terminal process.
+---------------------------------------------------------------------------*/
pid_t termProcPid = 0; /* pid of the terminal process */
/*---------------------------------------------------------------------------+
| StartTerminal - starts the terminal process.
+---------------------------------------------------------------------------*/
void
StartTerminal()
{
/* Child Process */
if ((termProcPid = SeFork()) == 0)
{Terminal(); exit(1);}
}
/*---------------------------------------------------------------------------+
| KillTerminal - kills the terminal process.
+---------------------------------------------------------------------------*/
void
KillTerminal()
{
void (*oldSigHandler)();
if (termProcPid == 0) return;
/* Make sure it's not suspended so that it can react to SIGTERM */
/* if (SuspContTerminal(TERM_CONTINUE) == 0) return;*/
oldSigHandler = signal(SIGCHLD, SIG_DFL);
/* Kill the child and wait for it to die */
if (termProcPid && kill(termProcPid, SIGTERM) == 0)
{while(wait((int*)0) < 0); termProcPid = 0;}
signal(SIGCHLD, oldSigHandler);
}
/*---------------------------------------------------------------------------+
| SuspContTerminal - suspends or resumes the terminal process.
+---------------------------------------------------------------------------*/
int
SuspContTerminal(state)
int state;
{
/* This variable keeps track of whether
the terminal is active or suspended */
static int termSuspended = 0;
if (termProcPid == 0) return 0;
if (state == TERM_CONTINUE) {
if (termProcPid && kill(termProcPid, SIGCONT) == 0)
termSuspended = 0;
return 1;
}
if (termSuspended) return 0;
if (termProcPid && kill(termProcPid, SIGUSR1) == 0)
{termSuspended = 1; return 1;}
else
return 0;
}
int
TerminalRefreshParameters()
{
int PutParameters();
if (termProcPid && (PutParameters(mainToTermPipe) < 0 ||
kill(termProcPid, SIGUSR2) != 0))
return -1;
else return 0;
}
/*
* Restart the terminal process (refresh) by killing it and starting a new
* one
*/
void
RestartTerminal()
{
KillTerminal();
StartTerminal();
}